<?php

namespace App\Tools;

use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Model\RestoreConfig;

Class AliyunUploadTool{
    public $model;

    public function __construct(){
        if (!empty($this->model)){

        }else{
            $this->model = new OssClient('LTAI5t9tFNzW77E6x1hGBAQH', 'eIgy9MxALeblzHZhLZjiIo6a3m05AY', 'oss-cn-hangzhou.aliyuncs.com');

        }
    }

    /**
     * Create a 'virtual' folder
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function createObjectDir($ossClient, $bucket)
    {
        try {
            $this->model->createObjectDir($bucket, "dir");
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }

    /**
     * Upload in-memory data to oss
     *
     * Simple upload---upload specified in-memory data to an OSS object
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function putObject($ossClient, $bucket)
    {
        $object = "oss-php-sdk-test/upload-test-object-name.txt";
        $content = file_get_contents(__FILE__);
        $options = array();
        try {
            $this->model->putObject($bucket, $object, $content, $options);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }


    /**
     * Uploads a local file to OSS
     * @param $filePath
     * @param $bucket
     * @param $object
     * @return void
     */
    public function uploadFile($bucket, $object, $filePath)
    {
        try {
            $this->model->uploadFile($bucket, $object, $filePath);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        unlink($filePath);
    }

    /**
     * Lists all files and folders in the bucket.
     * Note if there's more items than the max-keys specified, the caller needs to use the nextMarker returned as the value for the next call's maker paramter.
     * Loop through all the items returned from ListObjects.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function listObjects($ossClient, $bucket)
    {
        $prefix = 'oss-php-sdk-test/';
        $delimiter = '/';
        $nextMarker = '';
        $maxkeys = 1000;
        $options = array(
            'delimiter' => $delimiter,
            'prefix' => $prefix,
            'max-keys' => $maxkeys,
            'marker' => $nextMarker,
        );
        try {
            $listObjectInfo = $this->model->listObjects($bucket, $options);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
        $objectList = $listObjectInfo->getObjectList(); // object list
        $prefixList = $listObjectInfo->getPrefixList(); // directory list
        if (!empty($objectList)) {
            print("objectList:\n");
            foreach ($objectList as $objectInfo) {
                print($objectInfo->getKey() . "\n");
                if($objectInfo->getOwner() != null){
                    printf("owner id:".$objectInfo->getOwner()->getId() . "\n");
                    printf("owner name:".$objectInfo->getOwner()->getDisplayName() . "\n");
                }
            }
        }
        if (!empty($prefixList)) {
            print("prefixList: \n");
            foreach ($prefixList as $prefixInfo) {
                print($prefixInfo->getPrefix() . "\n");
            }
        }
    }

    /**
     * Lists all files and folders in the bucket.
     * Note if there's more items than the max-keys specified, the caller needs to use the nextMarker returned as the value for the next call's maker paramter.
     * Loop through all the items returned from ListObjects.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function listObjectsV2($ossClient, $bucket)
    {
        $prefix = 'oss-php-sdk-test/';
        $delimiter = '/';
        $maxkeys = 1000;
        $options = array(
            'delimiter' => $delimiter,
            'prefix' => $prefix,
            'max-keys' => $maxkeys,
            'start-after' =>'test-object',
            'fetch-owner' =>'true',
        );
        try {
            $listObjectInfo = $this->model->listObjectsV2($bucket, $options);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
        $objectList = $listObjectInfo->getObjectList(); // object list
        $prefixList = $listObjectInfo->getPrefixList(); // directory list
        if (!empty($objectList)) {
            print("objectList:\n");
            foreach ($objectList as $objectInfo) {
                print($objectInfo->getKey() . "\n");
                if($objectInfo->getOwner() != null){
                    printf("owner id:".$objectInfo->getOwner()->getId() . "\n");
                    printf("owner name:".$objectInfo->getOwner()->getDisplayName() . "\n");
                }
            }
        }
        if (!empty($prefixList)) {
            print("prefixList: \n");
            foreach ($prefixList as $prefixInfo) {
                print($prefixInfo->getPrefix() . "\n");
            }
        }
    }

    /**
     * Lists all folders and files under the bucket. Use nextMarker repeatedly to get all objects.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function listAllObjects($ossClient, $bucket)
    {
        // Create dir/obj 'folder' and put some files into it.
        for ($i = 0; $i < 100; $i += 1) {
            $this->model->putObject($bucket, "dir/obj" . strval($i), "hi");
            $this->model->createObjectDir($bucket, "dir/obj" . strval($i));
        }

        $prefix = 'dir/';
        $delimiter = '/';
        $nextMarker = '';
        $maxkeys = 30;

        while (true) {
            $options = array(
                'delimiter' => $delimiter,
                'prefix' => $prefix,
                'max-keys' => $maxkeys,
                'marker' => $nextMarker,
            );
            var_dump($options);
            try {
                $listObjectInfo = $this->model->listObjects($bucket, $options);
            } catch (OssException $e) {
                printf(__FUNCTION__ . ": FAILED\n");
                printf($e->getMessage() . "\n");
                return;
            }
            // Get the nextMarker, and it would be used as the next call's marker parameter to resume from the last call
            $nextMarker = $listObjectInfo->getNextMarker();
            $listObject = $listObjectInfo->getObjectList();
            $listPrefix = $listObjectInfo->getPrefixList();
            var_dump(count($listObject));
            var_dump(count($listPrefix));
            if ($nextMarker === '') {
                break;
            }
        }
    }

    /**
     * Get the content of an object.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function getObject($ossClient, $bucket)
    {
        $object = "oss-php-sdk-test/upload-test-object-name.txt";
        $options = array();
        try {
            $content = $this->model->getObject($bucket, $object, $options);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
        if (file_get_contents(__FILE__) === $content) {
            print(__FUNCTION__ . ": FileContent checked OK" . "\n");
        } else {
            print(__FUNCTION__ . ": FileContent checked FAILED" . "\n");
        }
    }

    /**
     * Put symlink
     *
     * @param OssClient $ossClient  The Instance of OssClient
     * @param string $bucket bucket name
     * @return null
     */
    public function putSymlink($ossClient, $bucket)
    {
        $symlink = "test-samples-symlink";
        $object = "test-samples-object";
        try {
            $this->model->putObject($bucket, $object, 'test-content');
            $this->model->putSymlink($bucket, $symlink, $object);
            $content = $this->model->getObject($bucket, $symlink);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
        if ($content == 'test-content') {
            print(__FUNCTION__ . ": putSymlink checked OK" . "\n");
        } else {
            print(__FUNCTION__ . ": putSymlink checked FAILED" . "\n");
        }
    }

    /**
     * Get symlink
     *
     * @param OssClient $ossClient  OssClient instance
     * @param string $bucket  bucket name
     * @return null
     */
    public function getSymlink($ossClient, $bucket)
    {
        $symlink = "test-samples-symlink";
        $object = "test-samples-object";
        try {
            $this->model->putObject($bucket, $object, 'test-content');
            $this->model->putSymlink($bucket, $symlink, $object);
            $content = $this->model->getSymlink($bucket, $symlink);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
        if ($content[OssClient::OSS_SYMLINK_TARGET]) {
            print(__FUNCTION__ . ": getSymlink checked OK" . "\n");
        } else {
            print(__FUNCTION__ . ": getSymlink checked FAILED" . "\n");
        }
    }

    /**
     * Get_object_to_local_file
     *
     * Get object
     * Download object to a specified file.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function getObjectToLocalFile($ossClient, $bucket)
    {
        $object = "oss-php-sdk-test/upload-test-object-name.txt";
        $localfile = "upload-test-object-name.txt";
        $options = array(
            OssClient::OSS_FILE_DOWNLOAD => $localfile,
        );

        try {
            $this->model->getObject($bucket, $object, $options);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK, please check localfile: 'upload-test-object-name.txt'" . "\n");
        if (file_get_contents($localfile) === file_get_contents(__FILE__)) {
            print(__FUNCTION__ . ": FileContent checked OK" . "\n");
        } else {
            print(__FUNCTION__ . ": FileContent checked FAILED" . "\n");
        }
        if (file_exists($localfile)) {
            unlink($localfile);
        }
    }

    /**
     * Copy object
     * When the source object is same as the target one, copy operation will just update the metadata.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function copyObject($ossClient, $bucket)
    {
        $fromBucket = $bucket;
        $fromObject = "oss-php-sdk-test/upload-test-object-name.txt";
        $toBucket = $bucket;
        $toObject = $fromObject . '.copy';
        $options = array();

        try {
            $this->model->copyObject($fromBucket, $fromObject, $toBucket, $toObject, $options);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }

    /**
     * Update Object Meta
     * it leverages the feature of copyObject： when the source object is just the target object, the metadata could be updated via copy
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function modifyMetaForObject($ossClient, $bucket)
    {
        $fromBucket = $bucket;
        $fromObject = "oss-php-sdk-test/upload-test-object-name.txt";
        $toBucket = $bucket;
        $toObject = $fromObject;
        $copyOptions = array(
            OssClient::OSS_HEADERS => array(
                'Cache-Control' => 'max-age=60',
                'Content-Disposition' => 'attachment; filename="xxxxxx"',
            ),
        );
        try {
            $this->model->copyObject($fromBucket, $fromObject, $toBucket, $toObject, $copyOptions);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }

    /**
     * Get object meta, that is, getObjectMeta
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function getObjectMeta($ossClient, $bucket)
    {
        $object = "oss-php-sdk-test/upload-test-object-name.txt";
        try {
            $objectMeta = $this->model->getObjectMeta($bucket, $object);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
        if (isset($objectMeta[strtolower('Content-Disposition')]) &&
            'attachment; filename="xxxxxx"' === $objectMeta[strtolower('Content-Disposition')]
        ) {
            print(__FUNCTION__ . ": ObjectMeta checked OK" . "\n");
        } else {
            print(__FUNCTION__ . ": ObjectMeta checked FAILED" . "\n");
        }
    }

    /**
     * Delete an object
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function deleteObject($ossClient, $bucket)
    {
        $object = "oss-php-sdk-test/upload-test-object-name.txt";
        try {
            $this->model->deleteObject($bucket, $object);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }


    /**
     * Delete multiple objects in batch
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function deleteObjects($ossClient, $bucket)
    {
        $objects = array();
        $objects[] = "oss-php-sdk-test/upload-test-object-name.txt";
        $objects[] = "oss-php-sdk-test/upload-test-object-name.txt.copy";
        try {
            $this->model->deleteObjects($bucket, $objects);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }

    /**
     * Check whether an object exists
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function doesObjectExist($ossClient, $bucket)
    {
        $object = "oss-php-sdk-test/upload-test-object-name.txt";
        try {
            $exist = $this->model->doesObjectExist($bucket, $object);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
        var_dump($exist);
    }

    /**
     * Speed limit upload.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function putObjectSpeed($ossClient, $bucket)
    {
        $object = "upload-test-object-name.txt";
        $content = file_get_contents(__FILE__);
        $options = array(
            OssClient::OSS_HEADERS => array(
                OssClient::OSS_TRAFFIC_LIMIT => 819200,
            ));
        try {
            $this->model->putObject($bucket, $object, $content, $options);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }

    /**
     * Speed limit download.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function getObjectSpeed($ossClient, $bucket)
    {
        $object = "upload-test-object-name.txt";
        $options = array(
            OssClient::OSS_HEADERS => array(
                OssClient::OSS_TRAFFIC_LIMIT => 819200,
            ));
        try {
            $this->model->getObject($bucket, $object, $options);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }

    /**
     * Speed limit download.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function signUrlSpeedUpload($ossClient, $bucket)
    {
        $object = "upload-test-object-name.txt";
        $timeout = 120;
        $options = array(
            OssClient::OSS_TRAFFIC_LIMIT => 819200,
        );
        $timeout = 60;
        $signedUrl = $this->model->signUrl($bucket, $object, $timeout, "PUT", $options);
        print($signedUrl);
    }


    /**
     * Speed limit download.
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function signUrlSpeedDownload($ossClient, $bucket)
    {
        $object = "upload-test-object-name.txt";
        $timeout = 120;
        $options = array(
            OssClient::OSS_TRAFFIC_LIMIT => 819200,
        );
        $signedUrl = $this->model->signUrl($bucket, $object, $timeout, "GET", $options);
        print($signedUrl);
        print(__FUNCTION__ . ": OK" . "\n");
    }

    /**
     * Restore object
     *
     * @param OssClient $ossClient OssClient instance
     * @param string $bucket bucket name
     * @return null
     */
    public function restoreObject($ossClient, $bucket)
    {
        $object = "oss-php-sdk-test/upload-test-object-name.txt";
        $day = 3;
        $tier = 'Expedited';
        $config = new RestoreConfig($day,$tier);
        $options = array(
            OssClient::OSS_RESTORE_CONFIG => $config
        );
        try {
            $this->model->restoreObject($bucket, $object,$options);
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        print(__FUNCTION__ . ": OK" . "\n");
    }
}
